package com.ye.auth.service;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ye.auth.dto.LoginBody;
import com.ye.auth.dto.RegisterBody;
import com.ye.common.redis.service.RedisCache;
import com.ye.common.security.dto.SecurityUser;
import com.ye.common.security.utils.JwtUtil;
import com.ye.common.security.utils.SecurityUtils;
import com.ye.common.utils.GenerateRandom;
import com.ye.common.utils.R;
import com.ye.core.exception.ServiceException;
import com.ye.system.user.entity.SysUser;
import com.ye.system.user.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * @Auther: baby
 * @Date: 2023/10/10 00:19
 * @Description:
 */
@Service
@Slf4j
public class SysLoginService implements UserDetailsService {

    @Autowired
    private SysUserService userService;
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Autowired
    private JwtUtil jwtUtils;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private AuthenticationManager authenticationManager;

    public R<?> register(RegisterBody registerBody) {

        String userName = registerBody.getUserName();
        if (StringUtils.isBlank(userName)) {
            do{
                userName= GenerateRandom.generateRandomString(GenerateRandom.USERNAME_LENGTH);
            }while (isUsernameExists(userName));
        }

        SysUser sysUser = new SysUser();
        sysUser.setUserName(userName);
        sysUser.setPassword(passwordEncoder.encode("123456"));
        try {
            userService.save(sysUser);
        } catch (Exception e) {
            throw new RuntimeException(String.format("注册失败：%s",e.getMessage()));
        }
        return R.ok();
    }

    private boolean isUsernameExists(String username) {
        return userService.count(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUserName,username))>0L;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser user = userService.getOne(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUserName,username),false);
        if (user == null) {
            log.info("username not found");
            throw new UsernameNotFoundException("username not found");
        }
        // todo 获取用户角色
        // 在这里将用户的权限转换为字符串数组
        List<String> list = new ArrayList<>(Arrays.asList("获取用户角色"));
        return new SecurityUser(user, list);
    }

    public R<?> login(LoginBody loginBody) {
        UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(loginBody.getUsername(), loginBody.getPassword());
        // 使用authenticationManager调用loadUserByUsername获取数据库中的用户信息,
        Authentication authentication = authenticationManager.authenticate(authToken);
        if(authentication == null) {
            throw new ServiceException("登录失败");
        }

        SecurityUser securityUser = (SecurityUser) authentication.getPrincipal();
        Long useId = securityUser.getUser().getId();

        List<String> authList = new ArrayList<String>();
        for (GrantedAuthority auth : securityUser.getAuthorities()) {
            authList.add(auth.getAuthority());
        }
        String jwt = JwtUtil.createJwt("user login", useId);
        // todo 存入Redis 设置缓存时间
        redisCache.setCacheObject("login:"+useId,securityUser);
        return R.ok(jwt);
    }

    public R<?> logout() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        SecurityUser loginUser = (SecurityUser) authentication.getPrincipal();
        redisCache.deleteObject("login:"+loginUser.getUser().getId());
        return R.ok();
    }

    public R<?> getUserInfo() {
        SecurityUser loginUser = SecurityUtils.getLoginUser();
        Integer userType = loginUser.getUser().getUserType();
        HashMap<String, Object> resultMap = new HashMap<>();
        resultMap.put("user",loginUser.getUser());
        List<String> roles = new ArrayList<>();
        if(userType==0){
            roles.add("admin");
        }
        resultMap.put("roles",roles);
        List<String> permissions= new ArrayList<>();
        resultMap.put("permissions",permissions);


        return R.ok(resultMap);

    }
}
